package com.yugao.fintech.draper.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.text.StrPool;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yugao.fintech.draper.admin.convert.TenantPackageConvert;
import com.yugao.fintech.draper.admin.entity.Tenant;
import com.yugao.fintech.draper.admin.entity.TenantPackage;
import com.yugao.fintech.draper.admin.mapper.TenantMapper;
import com.yugao.fintech.draper.admin.mapper.TenantPackageMapper;
import com.yugao.fintech.draper.admin.param.TenantPackageQuery;
import com.yugao.fintech.draper.admin.service.TenantPackageService;
import com.yugao.fintech.draper.admin.service.TenantService;
import com.yugao.fintech.draper.auth.dto.TenantPackageDTO;
import com.yugao.fintech.draper.core.enums.GlobalStatusEnum;
import com.yugao.fintech.draper.core.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

@Slf4j
@Service
public class TenantPackageServiceImpl extends ServiceImpl<TenantPackageMapper, TenantPackage> implements TenantPackageService {
    @Autowired
    private TenantMapper tenantMapper;
    @Autowired
    private TenantService tenantService;

    /**
     * 分页查询租户套餐信息
     */
    @Override
    public IPage<TenantPackageDTO> pageQuery(TenantPackageQuery tenantPackageQuery) {
        LambdaQueryWrapper<TenantPackage> wrapper = Wrappers.<TenantPackage>lambdaQuery()
                .eq(Objects.nonNull(tenantPackageQuery.getId()), TenantPackage::getId, tenantPackageQuery.getId())
                .eq(Objects.nonNull(tenantPackageQuery.getStatus()), TenantPackage::getStatus,
                        tenantPackageQuery.getStatus())
                .like(StrUtil.isNotBlank(tenantPackageQuery.getName()), TenantPackage::getName,
                        tenantPackageQuery.getName());
        Page<TenantPackage> packagePage = baseMapper.selectPage(Page.of(tenantPackageQuery.getPageNum(), tenantPackageQuery.getPageSize()), wrapper);
        return TenantPackageConvert.INSTANCE.convert(packagePage);
    }

    /**
     * 获取单条
     */
    @Override
    public TenantPackageDTO findById(Long id) {
        TenantPackage tenantPackage = baseMapper.selectById(id);
        return TenantPackageConvert.INSTANCE.convert(tenantPackage);
    }

    /**
     * 获取全部
     */
    @Override
    public List<TenantPackageDTO> findAll() {
        List<TenantPackage> tenantPackages = baseMapper.selectList(Wrappers.emptyWrapper());
        return TenantPackageConvert.INSTANCE.convert(tenantPackages);
    }

    /**
     * 添加
     */
    @Override
    public Boolean addTenantPackage(TenantPackageDTO tenantPackageDTO) {
        TenantPackage tenantPackage = TenantPackageConvert.INSTANCE.convert(tenantPackageDTO);
        return baseMapper.insert(tenantPackage) > 0;
    }

    /**
     * 更新租户套餐信息
     */
    @Override
    public Boolean updateTenantPackage(TenantPackageDTO tenantPackageDTO) {
        // 校验套餐是否存在
        TenantPackage packageExists = validTenantPackageExists(tenantPackageDTO.getId());
        // 更新套餐信息
        TenantPackage tenantPackage = TenantPackageConvert.INSTANCE.convert(tenantPackageDTO);
        baseMapper.updateById(tenantPackage);
        // 租户原菜单信息
        String[] newMenus = tenantPackageDTO.getMenuIds().split(StrPool.COMMA);
        // 更新后的菜单信息
        String[] oldMenus = packageExists.getMenuIds().split(StrPool.COMMA);
        // 菜单信息变化 则更新租户下的角色菜单信息
        if (!CollUtil.isEqualList(Arrays.asList(newMenus), Arrays.asList(oldMenus))) {
            // 本套餐下的所有租户
            List<Tenant> tenantList = tenantMapper.selectList(Wrappers.<Tenant>lambdaQuery().eq(Tenant::getPackageId, tenantPackageDTO.getId()));
            // 遍历所有租户 更新租户下的角色菜单信息
            tenantList.forEach(t -> tenantService.updateTenantRoleMenu(t.getId(), Arrays.asList(newMenus)));
        }
        return Boolean.TRUE;
    }

    /**
     * 删除租户套餐信息
     */
    @Override
    public Boolean deleteByTenantPackageId(Long id) {
        // 校验套餐是否存在
        validTenantPackageExists(id);
        // 校验套餐是否正在使用
        validTenantPackageUsed(id);
        // 删除套餐信息
        return baseMapper.deleteById(id) > 0;
    }

    /**
     * 校验套餐信息
     *
     * @param packageId 套餐id
     * @return 套餐信息
     */
    @Override
    public TenantPackage validTenantPackage(Long packageId) {
        TenantPackage tenantPackage = baseMapper.selectById(packageId);
        if (Objects.isNull(tenantPackage)) {
            throw new BaseException("租户套餐不存在！");
        } else if (GlobalStatusEnum.DISABLE.getValue().equals(tenantPackage.getStatus())) {
            throw new BaseException("套餐未开启！");
        }
        return tenantPackage;
    }

    /**
     * 校验套餐是否存在
     *
     * @param id 套餐id
     * @return 租户套餐
     */
    private TenantPackage validTenantPackageExists(Long id) {
        TenantPackage tenantPackage = baseMapper.selectById(id);
        if (Objects.isNull(tenantPackage)) {
            throw new BaseException("套餐信息不存在！更新失败！");
        }
        return tenantPackage;
    }

    private void validTenantPackageUsed(Long packageId) {
        Tenant tenant = tenantMapper.selectOne(Wrappers.<Tenant>lambdaQuery().eq(Tenant::getPackageId, packageId).last("limit 1"));
        if (Objects.nonNull(tenant)) {
            throw new BaseException("套餐信息使用！");
        }
    }
}